use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();

            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Result: {}", *counter.lock().unwrap());
}

#[cfg(test)]
mod tests {

    use std::time::Duration;
    use std::{sync::mpsc, thread};
    #[test]
    fn thread_move_variable() {
        let v = vec![1, 2, 3];

        let handle = thread::spawn(move || {
            println!("Here's a vector: {:?}", v);
        });

        handle.join().unwrap();
    }

    #[test]
    fn thread_communication_channel() {
        let (tx, rx) = mpsc::channel();

        thread::spawn(move || {
            let val = String::from("hi");
            tx.send(val).unwrap();
        });

        let received = rx.recv().unwrap();
        println!("Got: {}", received);
    }

    #[test]
    fn thread_communication_mutil_provider() {
        let (tx, rx) = mpsc::channel::<String>();
        thread::spawn(move || {
            println!("before tx done");
            drop(tx);
            thread::sleep(Duration::from_secs(2));
        });

        for received in rx {
            println!("Got: {}", received);
            thread::sleep(Duration::from_secs(1));
        }
        println!("main done");
    }
}
